import { Logger } from "./Logger";

const MongoClient = require('mongodb').MongoClient;

// const mongo = require('mongodb');

export class MongodbClient {

    public database: string;
    public host: string;
    public port: number;
    public user: string;
    public pass: string;
    public db: any

    public static async create(database: string, host: string, port: number, user: string, pass: string): Promise<MongodbClient> {
        return new Promise((resolve, reject) => {
            let client: MongodbClient = new MongodbClient();
            client.database = database;
            client.host = host;
            client.port = port
            client.user = user;
            client.pass = pass
            let url: string = 'mongodb://' + host + ":" + port;
            MongoClient.connect(url, (err, db_client) => {
                if (err) {
                    Logger.error("MongoClient connect error", err)
                    return;
                }
                const db = db_client.db(database);
                // client.close();
                client.db = db
                resolve(client)
            });
        })
    }

    public count(table_name: string): Promise<number> {
        return new Promise((resolve, reject) => {
            this.count_callback(table_name, (err, count) => {
                resolve(count)
            })
        })
    }

    private count_callback(table_name: string, callback: Function) {
        this.db.collection(table_name).countDocuments((err, count) => {
            if (err) {
                Logger.error("count error", err)
                callback && callback(err, 0)
                return;
            }
            Logger.log("count_callback suc==", count);
            callback && callback(err, count)
        })
        // this.db.collection(table_name).find().count((err, results)=>{
        //     if (err) {
        //         Logger.error("count error", err)
        //         callback && callback(err, [], [])
        //         return;
        //     }
        //     Logger.log("count_callback suc==", results);
        //     callback && callback(err, results)
        // })
    }

    public queryPromise(table_name: string, whereObj: object = {}): Promise<any> {
        return new Promise((resolve, reject) => {
            this.query_callback(table_name, whereObj, (err, results) => {
                resolve(results)
            })
        })
    }

    private query_callback(table_name: string, whereObj: object = {}, callback: Function = null) {
        this.db.collection(table_name).find(whereObj).toArray((err, results) => {
            if (err) {
                Logger.error("query error", err)
                callback && callback(err)
                return;
            }

            // Logger.log("query suc==", results);
            callback && callback(err, results)
        });
    }

    public createInex(table_name: string, indexName: string) {
        // this.db.collection(table_name).indexInformation((err, results)=>{
        //     Logger.log("indexInformation==err=", err)
        //     Logger.log("indexInformation=results==",results)
        // })
        this.db.collection(table_name).indexExists(indexName + "_1", (err, results) => {
            // Logger.log("indexExists==err=", err)
            // Logger.log("indexExists=results==", results)
            if (!results) {
                this.db.collection(table_name).createIndex(indexName, (err, results) => {
                    // Logger.log("createInex==err=", err)
                    // Logger.log("createInex=results==", results)
                })
            }
        })
    }

    public createIndex_callback() {

    }

    public insertOne(table_name: string, paramObj: object = {}) {
        return new Promise((resolve, reject) => {
            this.insertOne_callback(table_name, paramObj, (err, results) => {
                if (!err) {
                    resolve(results)
                } else {
                    resolve(null)
                }
            })
        })
    }

    private insertOne_callback(table_name: string, paramObj: object = {}, callback: Function = null) {
        this.db.collection(table_name).insertOne(paramObj, (err, results) => {
            if (err) {
                // Logger.error("insertOne error", err)
                callback && callback(err)
                return;
            }
            // Logger.log("insertOne suc==", results);
            callback && callback(err, results)
        })
    }

    public updateOne(table_name: string, whereObj: object = {}, updateObj: object = {}) {
        return new Promise((resolve, reject) => {
            this.updateOne_callback(table_name, whereObj, updateObj, (err, results, fields) => {
                resolve(results)
            })
        })
    }

    private updateOne_callback(table_name: string, whereObj: object = {}, updateObj: object = {}, callback: Function = null) {
        let realUpdateObj: object = { $set: updateObj };
        this.db.collection(table_name).updateOne(whereObj, realUpdateObj, (err, results) => {
            if (err) {
                Logger.error("updateOne error", err)
                callback && callback(err)
                return;
            }
            // Logger.log("updateOne suc==", results);
            callback && callback(err, results)
        })
    }

}